package io.gitee.zhangbinhub.admin.controller.api

import cn.dev33.satoken.annotation.SaCheckPermission
import cn.dev33.satoken.stp.StpUtil
import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.boot.log.LogAdapter
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import io.gitee.zhangbinhub.admin.api.ServerApi
import io.gitee.zhangbinhub.admin.base.BaseController
import io.gitee.zhangbinhub.admin.constant.ModuleFuncCode
import io.gitee.zhangbinhub.admin.constant.OauthConstant
import io.gitee.zhangbinhub.admin.constant.RoleCode
import io.gitee.zhangbinhub.admin.entity.User
import io.gitee.zhangbinhub.admin.po.UserInfoPo
import io.gitee.zhangbinhub.admin.po.UserPo
import io.gitee.zhangbinhub.admin.po.UserQueryPo
import io.gitee.zhangbinhub.admin.service.RuntimeConfigService
import io.gitee.zhangbinhub.admin.service.UserService
import io.gitee.zhangbinhub.admin.vo.CustomerQueryPageVo
import io.gitee.zhangbinhub.admin.vo.InfoVo
import io.gitee.zhangbinhub.admin.vo.UserVo
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import org.noear.solon.annotation.*
import org.noear.solon.core.handle.MethodType
import org.noear.solon.core.util.MimeType
import org.noear.solon.validation.annotation.*

@Valid
@Controller
@Api("用户信息")
open class UserController(
    @Inject logAdapter: LogAdapter,
    private val userService: UserService,
    private val runtimeConfigService: RuntimeConfigService
) : BaseController(logAdapter) {
    @ApiOperation(
        "获取当前用户信息", notes = "根据当前登录的用户信息，并查询详细信息，包含用户基本信息、所属角色、所属机构"
    )
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.currUser,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun userInfo(): User =
        (userService.getUserInfoByLoginNo(StpUtil.getLoginIdAsString())?.apply {
            if (this.lastUpdatePasswordTime == null) {
                this.passwordExpire = true
            } else {
                runtimeConfigService.findByName(OauthConstant.passwordUpdateIntervalTime)?.let { runtimeConfig ->
                    if (runtimeConfig.enabled && !CommonTools.isNullStr(runtimeConfig.value)) {
                        this.passwordExpire =
                            (System.currentTimeMillis() - this.lastUpdatePasswordTime!! - runtimeConfig.value!!.toLong()) >= 0
                    }
                }
            }
        } ?: throw WebException("找不到用户信息"))

    @ApiOperation(
        "更新当前用户信息",
        notes = "1、根据当前登录的用户信息，更新头像、名称、手机；2、如果原密码和新密码均不为空，校验原密码并修改为新密码"
    )
    @Mapping(
        method = [MethodType.PUT, MethodType.PATCH],
        value = ServerApi.basePath + ServerApi.currUser,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun updateCurrUser(@Body @Validated userInfoPo: UserInfoPo): User {
        val userInfo =
            userService.getUserInfoByLoginNo(StpUtil.getLoginIdAsString()) ?: throw WebException("找不到用户信息")
        userInfo.avatar = userInfoPo.avatar ?: ""
        userInfo.name = userInfoPo.name ?: userInfo.name
        userInfo.mobile = userInfoPo.mobile ?: userInfo.mobile
        if (!CommonTools.isNullStr(userInfoPo.oldPassword)) {
            if (CommonTools.isNullStr(userInfoPo.password)) {
                throw WebException("新密码为空")
            }
            if (userInfo.password.equals(userInfoPo.oldPassword!!, ignoreCase = true)) {
                userInfo.password = userInfoPo.password!!
                userInfo.lastUpdatePasswordTime = System.currentTimeMillis()
            } else {
                throw WebException("原密码不正确")
            }
        }
        return userService.doSaveUser(userInfo)
    }

    @ApiOperation("获取可管理的用户信息列表", notes = "根据当前登录的用户信息，获取可管理的用户信息列表")
    @SaCheckPermission(ModuleFuncCode.userConfig, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.modifiableUser,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    fun modifiableUser(): List<UserVo> = userService.findModifiableUserList(StpUtil.getLoginIdAsString())

    @ApiOperation(
        "新建用户信息",
        notes = "名称、登录账号、手机号、级别、序号、是否启用、关联机构、管理机构、关联角色"
    )
    @SaCheckPermission(ModuleFuncCode.userAdd, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.PUT],
        value = ServerApi.basePath + ServerApi.userConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun add(@Body @Validated userPo: UserPo): User = userService.doCreate(StpUtil.getLoginIdAsString(), userPo)

    @ApiOperation("删除指定的用户信息")
    @SaCheckPermission(ModuleFuncCode.userDelete, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.DELETE],
        value = ServerApi.basePath + ServerApi.userConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun delete(
        @ApiParam("id列表", required = true)
        @NotEmpty(message = "id不能为空")
        @NotNull(message = "id不能为空")
        @Body
        idList: MutableList<String>
    ): InfoVo = userService.doDelete(StpUtil.getLoginIdAsString(), idList).let { InfoVo(message = "删除成功") }

    @ApiOperation("更新用户信息", notes = "名称、手机号、级别、序号、是否启用、关联机构、管理机构、关联角色")
    @SaCheckPermission(ModuleFuncCode.userUpdate, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.PATCH],
        value = ServerApi.basePath + ServerApi.userConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun update(@Body @Validated userPo: UserPo): User {
        if (CommonTools.isNullStr(userPo.id)) {
            throw WebException("ID不能为空")
        }
        return userService.doUpdate(StpUtil.getLoginIdAsString(), userPo)
    }

    @ApiOperation("重置用户密码", notes = "根据用户ID查询详细信息并重置密码")
    @SaCheckPermission(ModuleFuncCode.userUpdate, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.userResetPwd + "/{userId}",
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun resetPwd(@Path(name = "userId") userId: String): InfoVo =
        userService.doUpdatePwd(StpUtil.getLoginIdAsString(), userId).let { InfoVo(message = "操作成功") }

    @ApiOperation("查询用户列表", notes = "查询条件：名称、登录帐号、状态、所属机构")
    @SaCheckPermission(ModuleFuncCode.userQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.POST],
        value = ServerApi.basePath + ServerApi.userConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun query(@Body @Validated userQueryPo: UserQueryPo): CustomerQueryPageVo<UserVo> =
        userService.doQuery(userQueryPo)

    @ApiOperation("查询用户信息（用户ID）", notes = "根据用户ID查询详细信息")
    @SaCheckPermission(ModuleFuncCode.userQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.userConfig + "/{userId}",
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun getUserInfo(@Path(name = "userId") userId: String): User =
        (userService.getUserInfoById(userId) ?: throw WebException("找不到用户信息"))

    @ApiOperation("查询用户信息（登录账号）", notes = "根据用户登录账号查询详细信息")
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.userConfig,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun getUserInfoByLoginNo(
        @ApiParam("登录账号", required = true)
        @NotBlank(message = "登录账号不能为空")
        @Param(name = "loginNo") loginNo: String
    ): UserVo = userService.getUserVoByLoginNo(loginNo)

    @ApiOperation("通过登录号或姓名，查询用户列表")
    @SaCheckPermission(ModuleFuncCode.userQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.userList + "-by-code-or-name",
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun getUserListByLoginNoOrName(
        @ApiParam("登录号或姓名", required = true)
        @NotBlank(message = "登录号或姓名不能为空")
        @Param(name = "loginNoOrName") loginNoOrName: String
    ): List<UserVo> = userService.getUserVoListByLoginNoOrName(loginNoOrName, false)

    @ApiOperation("通过相对机构级别和角色编码，查询用户列表")
    @SaCheckPermission(ModuleFuncCode.userQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.currOrgUserList,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun getUserListByCurrOrgAndRole(
        @ApiParam("机构层级")
        @NotBlank(message = "机构层级不能为空")
        @Param(name = "orgLevel") orgLevel: String?,
        @ApiParam("角色编码", required = true)
        @NotBlank(message = "角色编码不能为空")
        @Param(name = "roleCode") roleCode: String
    ): List<UserVo> = userService.getUserVoListByRelativeOrgAndRole(
        StpUtil.getLoginIdAsString(),
        orgLevel?.split(",")?.map { item -> item.toInt() } ?: listOf(0),
        roleCode.split(",")
    )

    @ApiOperation("通过机构编码和角色编码，查询用户列表")
    @SaCheckPermission(ModuleFuncCode.userQuery, orRole = [RoleCode.SUPER])
    @Mapping(
        method = [MethodType.GET],
        value = ServerApi.basePath + ServerApi.userList,
        produces = MimeType.APPLICATION_JSON_VALUE
    )
    @Throws(WebException::class)
    fun getUserListByOrgCodeAndRole(
        @ApiParam("机构编码")
        @Param(name = "orgCode") orgCode: String?,
        @ApiParam("角色编码", required = true)
        @NotBlank(message = "角色编码不能为空")
        @Param(name = "roleCode") roleCode: String
    ): List<UserVo> = if (orgCode == null) {
        userService.getUserVoListByRole(roleCode.split(","))
    } else {
        userService.getUserVoListByOrgCodeAndRole(orgCode.split(","), roleCode.split(","))
    }
}
